package work.mediway.mdm.biz.service.biz.impl;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import work.mediway.mdm.core.page.QueryRequest;
import work.mediway.mdm.biz.service.biz.MdmEditLogService;
import work.mediway.mdm.core.enums.StatusEditEnum;
import work.mediway.mdm.core.util.CommonUtil;
import work.mediway.mdm.biz.dto.biz.DictEditLogDTO;
import work.mediway.mdm.biz.dto.biz.PatientEditLogDTO;
import work.mediway.mdm.biz.entity.biz.MdmEditLog;
import work.mediway.mdm.biz.mapper.biz.MdmEditLogMapper;
import work.mediway.mdm.biz.vo.biz.DictEditLogVO;
import work.mediway.mdm.biz.vo.biz.PatientEditLogVO;

/**
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2021/1/22
 */
@Transactional(rollbackFor = Exception.class)
@Service
public class MdmEditLogServiceImpl extends ServiceImpl<MdmEditLogMapper, MdmEditLog> implements MdmEditLogService {

    @Override
    public Page<DictEditLogVO> listDictChangeLog(DictEditLogDTO editLogDTO, QueryRequest queryRequest) {
        /*editLogDTO.setType("字典");
        editLogDTO.setEditTypeCodeList(StrUtil.splitTrim(editLogDTO.getEditTypeCode(), StringPool.PIPE));
        editLogDTO.setType(DictEditLogDTO.TYPE_CODE.get(editLogDTO.getType()));*/
        Page<DictEditLogVO> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
        page.setOrders(OrderItem.descs("tableCode", "editUpdateDate", "editUpdateTime"));
        // 查询数据
        page.setRecords(this.baseMapper.listDictChangeLog(page, editLogDTO));
        page.getRecords().forEach(item -> {
            item.setEditUpdateDateTime(StrUtil.join(" ", item.getEditUpdateDate(), item.getEditUpdateTime()));
            item.setEditTypeDesc(StatusEditEnum.map.get(item.getEditTypeCode()));
            JSONObject afterDetail = JSONUtil.parseObj(item.getAfterEdit());
            String pre = CommonUtil.allUpperCase(item.getTableCode());
            List<DictEditLogVO.ChangeDetail> details = CollUtil.newArrayList();
            for (Map.Entry<String, Object> entry : afterDetail.entrySet()) {
                if (StrUtil.equalsIgnoreCase(entry.getKey(), "code")
                        || (StrUtil.equalsIgnoreCase(entry.getKey(), pre + "Code"))) {
                    item.setCode(String.valueOf(Optional.ofNullable(JSONUtil.parseObj(entry.getValue()).get("code")).orElse("")));
                    item.setDescr(String.valueOf(JSONUtil.parseObj(entry.getValue()).get("value")));
                }
                DictEditLogVO.ChangeDetail changeDetail = new DictEditLogVO.ChangeDetail();
                changeDetail.setFieldName(entry.getKey());
                changeDetail.setNewValue(String.valueOf(JSONUtil.parseObj(entry.getValue()).get("value")));
                changeDetail.setDescr(String.valueOf(JSONUtil.parseObj(entry.getValue()).get("desc")));
                changeDetail.setType(String.valueOf(JSONUtil.parseObj(entry.getValue()).get("type")));
                JSONObject beforeDetail = JSONUtil.parseObj(item.getBeforeEdit());
                for (Map.Entry<String, Object> en : beforeDetail.entrySet()) {
                    if (StrUtil.equalsIgnoreCase(entry.getKey(), en.getKey())) {
                        changeDetail.setOldValue(String.valueOf(JSONUtil.parseObj(en.getValue()).get("value")));
                        break;
                    }
                }
                details.add(changeDetail);
            }
            item.setDetails(details);
        });
        return page;
    }

    @Override
    public Page<PatientEditLogVO> listPatientChangeLog(PatientEditLogDTO editLogDTO, QueryRequest queryRequest) {
        editLogDTO.setType("患者");
        editLogDTO.setEditTypeCodeList(StrUtil.splitTrim(editLogDTO.getEditTypeCode(), StringPool.PIPE));
        editLogDTO.setType(DictEditLogDTO.TYPE_CODE.get(editLogDTO.getType()));

        Page<PatientEditLogVO> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
        page.setOrders(OrderItem.descs("tableCode", "editUpdateDate", "editUpdateTime"));
        page.setRecords(this.baseMapper.listPatientChangeLog(page, editLogDTO));

        page.getRecords().forEach(item -> {
            item.setEditUpdateDateTime(StrUtil.join(" ", item.getEditUpdateDate(), item.getEditUpdateTime()));
            item.setEditTypeDesc(StatusEditEnum.map.get(item.getEditTypeCode()));
            JSONObject afterDetail = JSONUtil.parseObj(item.getAfterEdit());
            List<PatientEditLogVO.ChangeDetail> details = CollUtil.newArrayList();
            for (Map.Entry<String, Object> entry : afterDetail.entrySet()) {
                PatientEditLogVO.ChangeDetail changeDetail = new PatientEditLogVO.ChangeDetail();
                changeDetail.setFieldName(entry.getKey());
                changeDetail.setNewValue(String.valueOf(JSONUtil.parseObj(entry.getValue()).get("value")));
                changeDetail.setDescr(String.valueOf(JSONUtil.parseObj(entry.getValue()).get("desc")));
                changeDetail.setType(String.valueOf(JSONUtil.parseObj(entry.getValue()).get("type")));
                JSONObject beforeDetail = JSONUtil.parseObj(item.getBeforeEdit());
                for (Map.Entry<String, Object> en : beforeDetail.entrySet()) {
                    if (StrUtil.equalsIgnoreCase(entry.getKey(), en.getKey())) {
                        changeDetail.setOldValue(String.valueOf(JSONUtil.parseObj(en.getValue()).get("value")));
                        break;
                    }
                }
                details.add(changeDetail);
            }
            item.setDetails(details);
        });
        return page;
    }

    @Override
    public MdmEditLog findOneLastedByTableRowId(String tableCode, String id) {
        return this.baseMapper.findOneLastedByTableRowId(tableCode, id);
    }
}
